home *** CD-ROM | disk | FTP | other *** search
- CHAPTER 6 THE 86 INSTRUCTION SET 6-1
-
- Since this is the start of the A86VxxxB.ARC file, I'll repeat
- here that the entire A86 package is Copyright (C)1986--1987 Eric
- Isaacson. All rights reserved. If this is all you've got, you
- need to get A86VxxxA.ARC, which contains the program and the
- first half of the manual.
-
-
- Effective Addresses
-
- Most memory data accessing in the 86 family is accomplished via
- the mechanism of the effective address. Wherever an effective
- address specifier "eb", "ew" or "ed" appears in the list of 8086
- instructions, you may use a wide variety of actual operands in
- that instruction. These include general registers, memory
- variables, and a variety of indexed memory quantities.
-
- GENERAL REGISTERS: Wherever an "ew" appears, you can use any of
- the 16-bit registers AX,BX,CX,DX,SI,DI,SP, or BP. Wherever an
- "eb" appears, you can use any of the 8-bit registers
- AL,BL,CL,DL,AH,BH,CH, or DH. For example, the "ADD ew,rw"
- form subsumes the 16-bit register-to-register adds; for
- example, ADD AX,BX; ADD SI,BP; ADD SP,AX.
-
- MEMORY VARIABLES: Wherever an "ew" appears, you can use a word-
- memory-variable. Wherever an "eb" appears, you can use a
- byte-memory-variable. Variables are typically declared in the
- DATA segment, using a DW declaration for a word-variable, or a
- DB declaration for a byte-variable. For example, you can
- declare variables:
-
- DATA_PTR DW ?
- ESC_CHAR DB ?
-
- Later, you can load or store these variables:
-
- MOV SI,DATA_PTR ; load DATA_PTR into SI for use
- LODSW ; fetch the word pointed to by DATA_PTR
- MOV DATA_PTR,SI ; store the value incremented by the LODSW
- MOV BL,ESC_CHAR ; load the byte-variable ESC_CHAR
-
- Alternatively, you can address specific unnamed memory
- locations by enclosing the location value in square brackets;
- for example,
-
- MOV AL,[02000] ; load contents of location 02000 into AL
-
- Note that A86 discerned from context (loading into AL) that a
- BYTE at 02000 was intended. Sometimes this is impossible, and
- you must specify byte or word:
-
- INC B[02000] ; increment the byte at location 02000
- MOV W[02000],0 ; set the WORD at location 02000 to zero
- 6-2
- INDEXED MEMORY: The 86 supports the use of certain registers as
- base pointers and index registers into memory. BX and BP are
- the base registers; SI and DI are the index registers. You
- may combine at most one base register, at most one index
- register, and a constant number into a run-time pointer that
- determines the location of the effective address memory to be
- used in the instruction. These can be given explicitly, by
- enclosing the index registers in brackets:
-
- MOV AX,[BX]
- MOV CX,W[SI+17]
- MOV AX,[BX+BP+5]
- MOV AX,[BX][BP]5 ; another way to write the same instr.
-
- Or, indexing can be accomplished by declaring variables in a
- based structure:
-
- STRUC [BP] ; NOTE based structures are unique to A86!
- BP_SAVE DW ?
- RET_ADDR DW ?
- PARM1 DW ?
- PARM2 DW ?
- ENDS
- INC PARM1 ; equivalent to INC W[BP+4]
-
- Finally, indexing can be done by mixing explicit components
- with declared ones:
-
- TABLE DB 4,2,1,3,5
- MOV AL,TABLE[BX]
-
-
- Segmentation and Effective Addresses
-
- The 86 family has four segment registers, CS, DS, ES, and SS,
- used to address memory. Each segment register points to 64K
- bytes of memory within the 1-megabyte memory space of the 86.
- (The start of the 64K is calculated by multiplying the segment
- register value by 16; i.e., by shifting the value left by one hex
- digit.) If your program's code, data and stack areas can all fit
- in the same 64K bytes, you can leave all the segment registers
- set to the same value. In that case, you won't have to think
- about segment registers--no matter which one is used to address
- memory, you'll still get the same 64K. If your program needs
- more than 64K, you must point one or more segment registers to
- other parts of the memory space. In this case, you must take
- care that your memory references use the segment registers you
- intended.
-
- Each effective address memory access has a default segment
- register, to be used if you do not explicitly specify which
- segment register you wish. For most effective addresses, the
- default segment register is DS. The exceptions are those
- effective addresses that use the BP register for indexing. All
- BP-indexed memory references have a default of SS. (This is
- because BP is intended to be used for addressing local variables,
- stored on the stack.)
- 6-3
- If you wish your memory access to use a different segment
- register, you provide a segment-override byte before the
- instruction containing the effective address operand. In the A86
- language, you code the override by giving the name of the segment
- register you wish before the instruction mnemonic. For example,
- suppose you want to load the AL register with the memory byte
- pointed to by BX. If you code MOV AL,[BX], the DS register will
- be used to determine which 64K segment BX is pointing to. If you
- want the byte to come from the CS-segment instead, you code CS
- MOV AL,[BX]. Be aware that the segment-override byte has effect
- only upon the single instruction that follows it. If you have a
- sequence of instructions requiring overrides, you must give an
- override byte before every instruction in the sequence. (In that
- case, you may wish to consider changing the value of the default
- segment register for the duration of the sequence.)
-
- NOTE: This method for providing segment-overrides is unique to
- the A86 assembler! The assemblers provided by Intel and IBM (MS-
- DOS) attempt to figure out segment allocation for you, and plug
- in segment-override bytes "behind your back". In order to do
- this, those assemblers require you to inform them which variables
- and structures are pointed to by which segment registers. That
- is what the ASSUME directive in those assemblers is all about. I
- wrote Intel's first 86 assembler, ASM86, so I have been watching
- the situation since day one. Over the years, I have concluded
- that the ASSUME-mechanism creates far, far more confusion that it
- solves. So I scrapped it; and the result is an assembler with
- far less red tape. But if your program needs more than 64K, you
- do have to manage those segment registers yourself; so take care!
-
-
- Effective Use of Effective Addresses
-
- Remember that all of the common instructions of the 86 family
- allow effective addresses as operands. (The only major functions
- that don't are the AL/AX specific ones: multiply, divide, and
- input/output). This means that you don't have to funnel many
- through AL or AX just to do something with them. You can perform
- all the common arithmetic, PUSH/POP, and MOVes from any general
- register to any general register; from any memory location
- (indexed if you like) to any register; and (this is most often
- overlooked) from any register TO memory. The only thing you
- can't do in general is memory-to-memory. Among the more common
- operations that inexperienced 86 programmers overlook are:
-
- * setting memory variables to immediate values
- * testing memory variables, and comparing them to constants
- * preserving memory variables by PUSHing and POPping them
- * incrementing and decrementing memory variables
- * adding into memory variables
- 6-4
- Encoding of Effective Addresses
-
- Unless you are concerned with the nitty-gritty details of 86
- instruction encoding, you don't need to read this section.
-
- Every instruction with an effective address has an encoded byte,
- known as the effective address byte, following the 1-byte opcode
- for the instruction. (For obscure reasons, Intel calls this byte
- the ModRM byte.) If the effective address is a memory variable,
- or an indexed memory location with a non-zero constant offset,
- then the effective address byte will be immediately followed by
- the offset amount. Amounts in the range -128 to +127 are given
- by a single signed byte, denoted by "d8" in the table below.
- Amounts requiring a 2-byte representation are denoted by "d16" in
- the table below. As with all 16-bit memory quantities in the 86
- family, the word is stored with the least significant byte FIRST.
-
- The following table of effective address byte values is organized
- into 32 rows and 8 columns. The 32 rows give the possible values
- for the effective address operand: 8 registers and 24 memory
- indexing modes. A 25th indexing mode, [BP] with zero
- displacement, has been pre-empted by the simple-memory-variable
- case. If you code [BP] with no displacement, you will get
- [BP]+d8, with a d8-value of zero.
-
- The 8 columns of the table reflect further information given by
- the effective address byte. Usually, this is the identity of the
- other (always a register) operand of a 2-operand instruction.
- Those instructions are identified by a "/r" following the opcode
- byte in the instruction list. Sometimes, the information given
- supplements the opcode byte in identifying the instruction
- itself. Those instructions are identified by a "/" followed by a
- digit from 0 through 7. The digit tells which of the 8 columns
- you should use to find the effective address byte.
-
- For example, suppose you have a perverse wish to know the precise
- bytes encoded by the instruction SUB B[BX+17],100. This
- instruction subtracts an immediate quantity, 100, from an
- effective address quantity, B[BX+17]. By consulting the
- instruction list, you find the general form SUB eb,ib. The
- opcode bytes given there are 80 /5 ib. The "/5" denotes an
- effective-address byte, whose value will be taken from column 5
- of the table below. The offset 17 decimal, which is 11 hex, will
- fit in a single "d8" byte, so we take our value from the "[BX] +
- d8" row. The table tells us that the effective address byte is
- 6F. Immediately following the 6F is the offset, 11 hex.
- Following that is the ib-value of 100 decimal, which is 64 hex.
- So the bytes generated by SUB B[BX+17],100 are 80 6F 11 64.
- 6-5
-
- Table of Effective Address byte values
-
- s = ES CS SS DS
- rb = AL CL DL BL AH CH DH BH
- rw = AX CX DX BX SP BP SI DI
- digit= 0 1 2 3 4 5 6 7
- Effective
- EA byte address:
- values: 00 08 10 18 20 28 30 38 [BX + SI]
- 01 09 11 19 21 29 31 39 [BX + DI]
- 02 0A 12 1A 22 2A 32 3A [BP + SI]
- 03 0B 13 1B 23 2B 33 3B [BP + DI]
- 04 0C 14 1C 24 2C 34 3C [SI]
- 05 0D 15 1D 25 2D 35 3D [DI]
- 06 0E 16 1E 26 2E 36 3E d16 (simple var)
- 07 0F 17 1F 27 2F 37 3F [BX]
- 40 48 50 58 60 68 70 78 [BX + SI] + d8
- 41 49 51 59 61 69 71 79 [BX + DI] + d8
- 42 4A 52 5A 62 6A 72 7A [BP + SI] + d8
- 43 4B 53 5B 63 6B 73 7B [BP + DI] + d8
- 44 4C 54 5C 64 6C 74 7C [SI] + d8
- 45 4D 55 5D 65 6D 75 7D [DI] + d8
- 46 4E 56 5E 66 6E 76 7E [BP] + d8
- 47 4F 57 5F 67 6F 77 7F [BX] + d8
- 80 88 90 98 A0 A8 B0 B8 [BX + SI] + d16
- 81 89 91 99 A1 A9 B1 B9 [BX + DI] + d16
- 82 8A 92 9A A2 AA B2 BA [BP + SI] + d16
- 83 8B 93 9B A3 AB B3 BB [BP + DI] + d16
- 84 8C 94 9C A4 AC B4 BC [SI] + d16
- 85 8D 95 9D A5 AD B5 BD [DI] + d16
- 86 8E 96 9E A6 AE B6 BE [BP] + d16
- 87 8F 97 9F A7 AF B7 BF [BX] + d16
- C0 C8 D0 D8 E0 E8 F0 F8 ew=AX eb=AL
- C1 C9 D1 D9 E1 E9 F1 F9 ew=CX eb=CL
- C2 CA D2 DA E2 EA F2 FA ew=DX eb=DL
- C3 CB D3 DB E3 EB F3 FB ew=BX eb=BL
- C4 CC D4 DC E4 EC F4 FC ew=SP eb=AH
- C5 CD D5 DD E5 ED F5 FD ew=BP eb=CH
- C6 CE D6 DE E6 EE F6 FE ew=SI eb=DH
- C7 CF D7 DF E7 EF F7 FF ew=DI eb=BH
-
- d8 denotes an 8-bit displacement following the EA byte,
- to be sign-extended and added to the index.
-
- d16 denotes a 16-bit displacement following the EA byte,
- to be added to the index.
-
- Default segment register is SS for effective addresses containing
- a BP index; DS for other memory effective addresses.
- 6-6
- How to Read the Instruction Set Chart
-
- The chart below summarizes the machine instructions you can
- program with A86. In order to use the chart, you need to learn
- the meanings of the specifiers (each given by 2 lower-case
- letters), that follow most of the instruction mnemonics. Each
- specifier indicates the type of operand (register byte, immediate
- word, etc.) that follows the mnemonic to produce the given
- opcodes.
-
- "c" means the operand is a code label, pointing to a part of the
- program to be jumped to or called. A86 will also accept a
- constant offset in this place (or a constant segment-offset
- pair in the case of "cd"). "cb" is a label within about 128
- bytes (in either direction) of the current location. "cw" is
- a label within the same code segment as this program; "cd" is
- a pair of constants separated by a colon-- the segment value
- to the left of the colon, and the offset to the right. Note
- that in both the cb and cw cases, the object code generated
- is the offset from the location following the current
- instruction, not the absolute location of the label operand.
- In some assemblers (most notably for the Z-80 processor) you
- have to code this offset explicitly by putting "$-" before
- every relative jump operand in your source code. You do NOT
- need to, and should not do so with A86.
-
- "e" means the operand is an Effective Address. The concept of an
- Effective Address is central to the 86 machine architecture,
- and thus to 86 assembly language programming. It is
- described in detail at the start of Chapter 8. We summarize
- here by saying that an Effective Address is either a general-
- purpose register, a memory variable, or an indexed memory
- quantity. For example, the instruction "ADD rb,eb" includes
- the instructions: ADD AL,BL, or ADD CH,BYTEVAR, or ADD
- DL,B[BX+17].
-
- "i" means the operand is an immediate constant, provided as part
- of the instruction itself. "ib" is a byte-sized constant;
- "iw" is a constant occupying a full 16-bit word. The operand
- can also be a label, defined with a colon. In that case, the
- immediate constant which is the location of the label is
- used. Examples: "MOV rw,iw" includes the instructions: MOV
- AX,17, or MOV SI,VAR_ARRAY, where "VAR_ARRAY:" appears
- somewhere in the program, defined with a colon. NOTE that if
- VAR_ARRAY were defined without a colon, e.g., "VAR_ARRAY DW
- 1,2,3", then "MOV SI,VAR_ARRAY" would be a "MOV rw,ew" NOT a
- "MOV rw,iw". The MOV would move the contents of memory at
- VAR_ARRAY (in this case 1) into SI, instead of the location
- of the memory. To load the location, you can code "MOV
- SI,OFFSET VAR_ARRAY".
-
- "m" means a memory variable or an indexed memory quantity; i.e.,
- any Effective Address EXCEPT a register.
-
- "r" means the operand is a general-purpose register. The 8 "rb"
- registers are AL,BL,CL,DL,AH,BH,CH,DH; the 8 "rw" registers
- are AX,BX,CX,DX,SI, DI,BP,SP.
- 6-7
-
- WARNING: Instruction forms marked with "*" by the mnemonic are
- part of the extended 186/286/NEC instruction set.
- Instructions marked with "#" are unique to the NEC
- processors. These instructions will NOT work on the 8088 of
- the IBM-PC; nor will they work on the 8086; nor will the NEC
- instructions work on the 186 or 286. If you wish your
- programs to run on all PC's, do not use these instructions!
-
- Opcodes Instruction Description
- ------- ----------- -----------
- 37 AAA ASCII adjust AL (carry into AH) after addition
- D5 0A AAD ASCII adjust before division (AX = 10*AH + AL)
- D4 0A AAM ASCII adjust after multiply (AL/10: AH=Quo AL=Rem)
- 3F AAS ASCII adjust AL (borrow from AH) after subtraction
- 14 ib ADC AL,ib Add with carry immediate byte into AL
- 15 iw ADC AX,iw Add with carry immediate word into AX
- 80 /2 ib ADC eb,ib Add with carry immediate byte into EA byte
- 10 /r ADC eb,rb Add with carry byte register into EA byte
- 83 /2 ib ADC ew,ib Add with carry immediate byte into EA word
- 81 /2 iw ADC ew,iw Add with carry immediate word into EA word
- 11 /r ADC ew,rw Add with carry word register into EA word
- 12 /r ADC rb,eb Add with carry EA byte into byte register
- 13 /r ADC rw,ew Add with carry EA word into word register
- 04 ib ADD AL,ib Add immediate byte into AL
- 05 iw ADD AX,iw Add immediate word into AX
- 80 /0 ib ADD eb,ib Add immediate byte into EA byte
- 00 /r ADD eb,rb Add byte register into EA byte
- 83 /0 ib ADD ew,ib Add immediate byte into EA word
- 81 /0 iw ADD ew,iw Add immediate word into EA word
- 01 /r ADD ew,rw Add word register into EA word
- 02 /r ADD rb,eb Add EA byte into byte register
- 03 /r ADD rw,ew Add EA word into word register
- 0F 20 #ADD4S Add CL nibbles BCD from DS:SI into ES:DI (CL even,NZ)
- 24 ib AND AL,ib Logical-AND immediate byte into AL
- 25 iw AND AX,iw Logical-AND immediate word into AX
- 80 /4 ib AND eb,ib Logical-AND immediate byte into EA byte
- 20 /r AND eb,rb Logical-AND byte register into EA byte
- 81 /4 iw AND ew,iw Logical-AND immediate word into EA word
- 21 /r AND ew,rw Logical-AND word register into EA word
- 22 /r AND rb,eb Logical-AND EA byte into byte register
- 23 /r AND rw,ew Logical-AND EA word into word register
- 63 /r *ARPL ew,rw Adjust RPL of EA word not smaller than RPL of rw
- 62 /r *BOUND rw,md INT 5 if rw not between [md] and [md+2] inclusive
- 9A cd CALL cd Call far segment, immediate 4-byte address
- E8 cw CALL cw Call near, offset relative to next instruction
- FF /3 CALL ed Call far segment, address at EA doubleword
- FF /2 CALL ew Call near, offset absolute at EA word
- 0F FF ib #CALL80 ib Call 8080-emulation code at INT number ib
- 98 CBW Convert byte into word (AH = top bit of AL)
- F8 CLC Clear carry flag
- FC CLD Clear direction flag so SI and DI will increment
- FA CLI Clear interrupt enable flag; interrupts disabled
- 0F 12/0 #CLRBIT eb,CL Clear bit CL of eb
- 0F 13/0 #CLRBIT ew,CL Clear bit CL of ew
- 0F 1A/0 ib #CLRBIT eb,ib Clear bit ib of eb
- 0F 1B/0 ib #CLRBIT ew,ib Clear bit ib of ew
- 6-8
-
- 0F 06 *CLTS Clear task switched flag
- F5 CMC Complement carry flag
- 3C ib CMP AL,ib Subtract immediate byte from AL for flags only
- 3D iw CMP AX,iw Subtract immediate word from AX for flags only
- 80 /7 ib CMP eb,ib Subtract immediate byte from EA byte for flags only
- 38 /r CMP eb,rb Subtract byte register from EA byte for flags only
- 83 /7 ib CMP ew,ib Subtract immediate byte from EA word for flags only
- 81 /7 iw CMP ew,iw Subtract immediate word from EA word for flags only
- 39 /r CMP ew,rw Subtract word register from EA word for flags only
- 3A /r CMP rb,eb Subtract EA byte from byte register for flags only
- 3B /r CMP rw,ew Subtract EA word from word register for flags only
- 0F 26 #CMP4S Compare CL nibbles CD at DS:SI from ES:DI (CL even,NZ)
- A6 CMPS mb,mb Compare bytes ES:[DI] from [SI], advance SI and DI
- A7 CMPS mw,mw Compare words ES:[DI] from [SI], advance SI and DI
- A6 CMPSB Compare bytes ES:[DI] from DS:[SI], advance SI and DI
- A7 CMPSW Compare words ES:[DI] from DS:[SI], advance SI and DI
- 99 CWD Convert word to doubleword (DX = top bit of AX)
- 27 DAA Decimal adjust AL after addition
- 2F DAS Decimal adjust AL after subtraction
- FE /1 DEC eb Decrement EA byte by 1
- FF /1 DEC ew Decrement EA word by 1
- 48+rw DEC rw Decrement word register by 1
- F6 /6 DIV eb Unsigned divide AX by EA byte (AL=Quo AH=Rem)
- F7 /6 DIV ew Unsigned divide DXAX by EA word (AX=Quo DX=Rem)
- C8 iw 00 *ENTER iw,0 Make stack frame, iw bytes local storage, 0 levels
- C8 iw 01 *ENTER iw,1 Make stack frame, iw bytes local storage, 1 level
- C8 iw ib *ENTER iw,ib Make stack frame, iw bytes local storage, ib levels
- Fany Floating point set is in Chapter 7
- F4 HLT Halt
- F6 /7 IDIV eb Signed divide AX by EA byte (AL=Quo AH=Rem)
- F7 /7 IDIV ew Signed divide DXAX by EA word (AX=Quo DX=Rem)
- F6 /5 IMUL eb Signed multiply (AX = AL * EA byte)
- F7 /5 IMUL ew Signed multiply (DXAX = AX * EA word)
- 6B /r ib *IMUL rw,ib Signed multiply immediate byte into word register
- 69 /r iw *IMUL rw,iw Signed multiply immediate word into word register
- 69 /r iw *IMUL rw,ew,iw Signed multiply (rw = EA word * immediate word)
- 6B /r ib *IMUL rw,ew,ib Signed multiply (rw = EA word * immediate byte)
- E4 ib IN AL,ib Input byte from immediate port into AL
- EC IN AL,DX Input byte from port DX into AL
- E5 ib IN AX,ib Input word from immediate port into AX
- ED IN AX,DX Input word from port DX into AX
- FE /0 INC eb Increment EA byte by 1
- FF /0 INC ew Increment EA word by 1
- 40+rw INC rw Increment word register by 1
- 6C *INS eb,DX Input byte from port DX into [DI]
- 6D *INS ew,DX Input word from port DX into [DI]
- 6C *INSB Input byte from port DX into ES:[DI]
- 6D *INSW Input word from port DX into ES:[DI]
- CC INT 3 Interrupt 3 (trap to debugger) (far call, with flags
- CD ib INT ib Interrupt numbered by immediate byte pushed first)
- CE INTO Interrupt 4 if overflow flag is 1
- CF IRET Interrupt return (far return and pop flags)
- 6-9
-
- 77 cb JA cb Jump short if above (CF=0 and ZF=0) above=UNSIGNED
- 73 cb JAE cb Jump short if above or equal (CF=0)
- 72 cb JB cb Jump short if below (CF=1) below=UNSIGNED
- 76 cb JBE cb Jump short if below or equal (CF=1 or ZF=1)
- 72 cb JC cb Jump short if carry (CF=1)
- E3 cb JCXZ cb Jump short if CX register is zero
- 74 cb JE cb Jump short if equal (ZF=1)
- 7F cb JG cb Jump short if greater (ZF=0 and SF=OF) greater=SIGNED
- 7D cb JGE cb Jump short if greater or equal (SF=OF)
- 7C cb JL cb Jump short if less (SF/=OF) less=SIGNED
- 7E cb JLE cb Jump short if less or equal (ZF=1 or SF/=OF)
- EB cb JMP cb Jump short (signed byte relative to next instruction)
- EA cd JMP cd Jump far (4-byte immediate address)
- E9 cw JMP cw Jump near (word offset relative to next instruction)
- FF /4 JMP ew Jump near to EA word (absolute offset)
- FF /5 JMP md Jump far (4-byte address in memory doubleword)
- 76 cb JNA cb Jump short if not above (CF=1 or ZF=1)
- 72 cb JNAE cb Jump short if not above or equal (CF=1)
- 73 cb JNB cb Jump short if not below (CF=0)
- 77 cb JNBE cb Jump short if not below or equal (CF=0 and ZF=0)
- 73 cb JNC cb Jump short if not carry (CF=0)
- 75 cb JNE cb Jump short if not equal (ZF=0)
- 7E cb JNG cb Jump short if not greater (ZF=1 or SF/=OF)
- 7C cb JNGE cb Jump short if not greater or equal (SF/=OF)
- 7D cb JNL cb Jump short if not less (SF=OF)
- 7F cb JNLE cb Jump short if not less or equal (ZF=0 and SF=OF)
- 71 cb JNO cb Jump short if not overflow (OF=0)
- 7B cb JNP cb Jump short if not parity (PF=0)
- 79 cb JNS cb Jump short if not sign (SF=0)
- 75 cb JNZ cb Jump short if not zero (ZF=0)
- 70 cb JO cb Jump short if overflow (OF=1)
- 7A cb JP cb Jump short if parity (PF=1)
- 7A cb JPE cb Jump short if parity even (PF=1)
- 7B cb JPO cb Jump short if parity odd (PF=0)
- 78 cb JS cb Jump short if sign (SF=1)
- 74 cb JZ cb Jump short if zero (ZF=1)
- 9F LAHF Load: AH = flags SF ZF xx AF xx PF xx CF
- 0F 02 /r *LAR rw,ew Load: high(rw) = Access Rights byte, selector ew
- C5 /r LDS rw,ed Load EA doubleword into DS and word register
- 8D /r LEA rw,m Calculate EA offset given by M, place in rw
- C9 *LEAVE Set SP to BP, then POP BP (reverses previous ENTER)
- C4 /r LES rw,ed Load EA doubleword into ES and word register
- 0F 01 /2 *LGDT m Load 6 bytes at m into Global Descriptor Table reg
- 0F 01 /3 *LIDT m Load 6 bytes at m into Interrupt Descriptor Table reg
- 0F 00 /2 *LLDT ew Load selector ew into Local Descriptor Table reg
- 0F 01 /6 *LMSW ew Load EA word into Machine Status Word
- F0 LOCK (prefix) Assert BUSLOCK signal for the next instruction
- 0F 33/r #LODBITS rb,rb Load AX with DS:SI,bit rb (incr. SI,rb), rb+1 bits
- 0F 3B/0 ib #LODBITS rb,ib Load AX with DS:SI,bit rb (incr. SI,rb), ib+1 bits
- AC LODS mb Load byte [SI] into AL, advance SI
- AD LODS mw Load byte [SI] into AL, advance SI
- AC LODSB Load byte [SI] into AL, advance SI
- AD LODSW Load byte [SI] into AL, advance SI
- 6-10
-
- E2 cb LOOP cb noflags DEC CX; jump short if CX/=0
- E1 cb LOOPE cb noflags DEC CX; jump short if CX/=0 and equal (ZF=1)
- E0 cb LOOPNE cb noflags DEC CX; jump short if CX/=0 and not equal
- E0 cb LOOPNZ cb noflags DEC CX; jump short if CX/=0 and ZF=0
- E1 cb LOOPZ cb noflags DEC CX; jump short if CX/=0 and zero (ZF=1)
- 0F 03 /r *LSL rw,ew Load: rw = Segment Limit, selector ew
- 0F 00 /3 *LTR ew Load EA word into Task Register
- A0 iw MOV AL,xb Move byte variable (offset iw) into AL
- A1 iw MOV AX,xw Move word variable (offset iw) into AX
- 8E /3 MOV DS,mw Move memory word into DS
- 8E /3 MOV DS,rw Move word register into DS
- C6 /0 ib MOV eb,ib Move immediate byte into EA byte
- 88 /r MOV eb,rb Move byte register into EA byte
- 8E /0 MOV ES,mw Move memory word into ES
- 8E /0 MOV ES,rw Move word register into ES
- 8C /1 MOV ew,CS Move CS into EA word
- 8C /3 MOV ew,DS Move DS into EA word
- C7 /0 iw MOV ew,iw Move immediate word into EA word
- 8C /0 MOV ew,ES Move ES into EA word
- 89 /r MOV ew,rw Move word register into EA word
- 8C /2 MOV ew,SS Move SS into EA word
- B0+rb ib MOV rb,ib Move immediate byte into byte register
- 8A /r MOV rb,eb Move EA byte into byte register
- B8+rw iw MOV rw,iw Move immediate word into word register
- 8B /r MOV rw,ew Move EA word into word register
- 8E /2 MOV SS,mw Move memory word into SS
- 8E /2 MOV SS,rw Move word register into SS
- A2 iw MOV xb,AL Move AL into byte variable (offset iw)
- A3 iw MOV xw,AX Move AX into word register (offset iw)
- A4 MOVS mb,mb Move byte [SI] to ES:[DI], advance SI and DI
- A5 MOVS mw,mw Move word [SI] to ES:[DI], advance SI and DI
- A4 MOVSB Move byte DS:[SI] to ES:[DI], advance SI and DI
- A5 MOVSW Move word DS:[SI] to ES:[DI], advance SI and DI
- F6 /4 MUL eb Unsigned multiply (AX = AL * EA byte)
- F7 /4 MUL ew Unsigned multiply (DXAX = AX * EA word)
- F6 /3 NEG eb Two's complement negate EA byte
- F7 /3 NEG ew Two's complement negate EA word
- NIL (prefix) Special "do-nothing" opcode assembles no code
- 90 NOP No Operation
- F6 /2 NOT eb Reverse each bit of EA byte
- F7 /2 NOT ew Reverse each bit of EA word
- 0F 16/0 #NOTBIT eb,CL Complement bit CL of eb
- 0F 17/0 #NOTBIT ew,CL Complement bit CL of ew
- 0F 1E/0 ib #NOTBIT eb,ib Complement bit ib of eb
- 0F 1F/0 ib #NOTBIT ew,ib Complement bit ib of ew
- 0C ib OR AL,ib Logical-OR immediate byte into AL
- 0D iw OR AX,iw Logical-OR immediate word into AX
- 80 /1 ib OR eb,ib Logical-OR immediate byte into EA byte
- 08 /r OR eb,rb Logical-OR byte register into EA byte
- 81 /1 iw OR ew,iw Logical-OR immediate word into EA word
- 09 /r OR ew,rw Logical-OR word register into EA word
- 0A /r OR rb,eb Logical-OR EA byte into byte register
- 0B /r OR rw,ew Logical-OR EA word into word register
- 6-11
-
- E6 ib OUT ib,AL Output byte AL to immediate port number ib
- E7 ib OUT ib,AX Output word AX to immediate port number ib
- EE OUT DX,AL Output byte AL to port number DX
- EF OUT DX,AX Output word AX to port number DX
- 6E *OUTS DX,eb Output byte [SI] to port number DX, advance SI
- 6F *OUTS DX,ew Output word [SI] to port number DX, advance SI
- 6E *OUTSB Output byte DS:[SI] to port number DX, advance SI
- 6F *OUTSW Output word DS:[SI] to port number DX, advance SI
- 1F POP DS Set DS to top of stack, increment SP by 2
- 07 POP ES Set ES to top of stack, increment SP by 2
- 8F /0 POP mw Set memory word to top of stack, increment SP by 2
- 58+rw POP rw Set word register to top of stack, increment SP by 2
- 17 POP SS Set SS to top of stack, increment SP by 2
- 61 *POPA Pop DI,SI,BP,SP,BX,DX,CX,AX (SP value is ignored)
- 9D POPF Set flags register to top of stack, increment SP by 2
- 0E PUSH CS Set [SP-2] to CS, then decrement SP by 2
- 1E PUSH DS Set [SP-2] to DS, then decrement SP by 2
- 06 PUSH ES Set [SP-2] to ES, then decrement SP by 2
- 6A ib *PUSH ib Push sign-extended immediate byte
- 68 iw *PUSH iw Set [SP-2] to immediate word, then decrement SP by 2
- FF /6 PUSH mw Set [SP-2] to memory word, then decrement SP by 2
- 50+rw PUSH rw Set [SP-2] to word register, then decrement SP by 2
- 16 PUSH SS Set [SP-2] to SS, then decrement SP by 2
- 60 *PUSHA Push AX,CX,DX,BX,original SP,BP,SI,DI
- 9C PUSHF Set [SP-2] to flags register, then decrement SP by 2
- D0 /2 RCL eb,1 Rotate 9-bit quantity (CF, EA byte) left once
- D2 /2 RCL eb,CL Rotate 9-bit quantity (CF, EA byte) left CL times
- C0 /2 ib *RCL eb,ib Rotate 9-bit quantity (CF, EA byte) left ib times
- D1 /2 RCL ew,1 Rotate 17-bit quantity (CF, EA word) left once
- D3 /2 RCL ew,CL Rotate 17-bit quantity (CF, EA word) left CL times
- C1 /2 ib *RCL ew,ib Rotate 17-bit quantity (CF, EA word) left ib times
- D0 /3 RCR eb,1 Rotate 9-bit quantity (CF, EA byte) right once
- D2 /3 RCR eb,CL Rotate 9-bit quantity (CF, EA byte) right CL times
- C0 /3 ib *RCR eb,ib Rotate 9-bit quantity (CF, EA byte) right ib times
- D1 /3 RCR ew,1 Rotate 17-bit quantity (CF, EA word) right once
- D3 /3 RCR ew,CL Rotate 17-bit quantity (CF, EA word) right CL times
- C1 /3 ib *RCR ew,ib Rotate 17-bit quantity (CF, EA word) right ib times
- F3 REP (prefix) Repeat following MOVS,LODS,STOS,INS, or OUTS CX times
- 65 #REPC (prefix) Repeat following CMPS or SCAS CX times or until CF=0
- F3 REPE (prefix) Repeat following CMPS or SCAS CX times or until ZF=0
- 64 #REPNC (prefix)Repeat following CMPS or SCAS CX times or until CF=1
- F2 REPNE (prefix)Repeat following CMPS or SCAS CX times or until ZF=1
- F2 REPNZ (prefix)Repeat following CMPS or SCAS CX times or until ZF=0
- F3 REPZ (prefix) Repeat following CMPS or SCAS CX times or until ZF=1
- CB RETF Return to far caller (pop offset, then seg)
- C3 RET Return to near caller (pop offset only)
- CA iw RETF iw RET (far), pop offset, seg, iw bytes
- C2 iw RET iw RET (near), pop offset, iw bytes pushed before Call
- 6-12
-
- D0 /0 ROL eb,1 Rotate 8-bit EA byte left once
- D2 /0 ROL eb,CL Rotate 8-bit EA byte left CL times
- C0 /0 ib *ROL eb,ib Rotate 8-bit EA byte left ib times
- D1 /0 ROL ew,1 Rotate 16-bit EA word left once
- D3 /0 ROL ew,CL Rotate 16-bit EA word left CL times
- C1 /0 ib *ROL ew,ib Rotate 16-bit EA word left ib times
- 0F 28/0 #ROL4 eb Rotate nibbles: Heb=Leb HAL,Leb=LAL LAL=Heb
- D0 /1 ROR eb,1 Rotate 8-bit EA byte right once
- D2 /1 ROR eb,CL Rotate 8-bit EA byte right CL times
- C0 /1 ib *ROR eb,ib Rotate 8-bit EA byte right ib times
- D1 /1 ROR ew,1 Rotate 16-bit EA word right once
- D3 /1 ROR ew,CL Rotate 16-bit EA word right CL times
- C1 /1 ib *ROR ew,ib Rotate 16-bit EA word right ib times
- 0F 2A/0 #ROR4 eb Rotate nibbles: Leb=Heb Heb=LAL AL=eb
- 9E SAHF Store AH into flags SF ZF xx AF xx PF xx CF
- D0 /4 SAL eb,1 Multiply EA byte by 2, once
- D2 /4 SAL eb,CL Multiply EA byte by 2, CL times
- C0 /4 ib *SAL eb,ib Multiply EA byte by 2, ib times
- D1 /4 SAL ew,1 Multiply EA word by 2, once
- D3 /4 SAL ew,CL Multiply EA word by 2, CL times
- C1 /4 ib *SAL ew,ib Multiply EA word by 2, ib times
- D0 /7 SAR eb,1 Signed divide EA byte by 2, once
- D2 /7 SAR eb,CL Signed divide EA byte by 2, CL times
- C0 /7 ib *SAR eb,ib Signed divide EA byte by 2, ib times
- D1 /7 SAR ew,1 Signed divide EA word by 2, once
- D3 /7 SAR ew,CL Signed divide EA word by 2, CL times
- C1 /7 ib *SAR ew,ib Signed divide EA word by 2, ib times
- 1C ib SBB AL,ib Subtract with borrow immediate byte from AL
- 1D iw SBB AX,iw Subtract with borrow immediate word from AX
- 80 /3 ib SBB eb,ib Subtract with borrow immediate byte from EA byte
- 18 /r SBB eb,rb Subtract with borrow byte register from EA byte
- 83 /3 ib SBB ew,ib Subtract with borrow immediate byte from EA word
- 81 /3 iw SBB ew,iw Subtract with borrow immediate word from EA word
- 19 /r SBB ew,rw Subtract with borrow word register from EA word
- 1A /r SBB rb,eb Subtract with borrow EA byte from byte register
- 1B /r SBB rw,ew Subtract with borrow EA word from word register
- AE SCAS mb Compare bytes AL - ES:[DI], advance DI
- AF SCAS mw Compare words AL - ES:[DI], advance DI
- AE SCASB Compare bytes AX - ES:[DI], advance DI
- AF SCASW Compare words AX - ES:[DI], advance DI
- 0F 14/0 #SETBIT eb,CL Set bit CL of eb
- 0F 15/0 #SETBIT ew,CL Set bit CL of ew
- 0F 1C/0 ib #SETBIT eb,ib Set bit ib of eb
- 0F 1D/0 ib #SETBIT ew,ib Set bit ib of ew
- 0F 01 /0 *SGDT m Store 6-byte Global Descriptor Table register to M
- D0 /4 SHL eb,1 Multiply EA byte by 2, once
- D2 /4 SHL eb,CL Multiply EA byte by 2, CL times
- C0 /4 ib *SHL eb,ib Multiply EA byte by 2, ib times
- D1 /4 SHL ew,1 Multiply EA word by 2, once
- D3 /4 SHL ew,CL Multiply EA word by 2, CL times
- C1 /4 ib *SHL ew,ib Multiply EA word by 2, ib times
- 6-13
-
- D0 /5 SHR eb,1 Unsigned divide EA byte by 2, once
- D2 /5 SHR eb,CL Unsigned divide EA byte by 2, CL times
- C0 /5 ib *SHR eb,ib Unsigned divide EA byte by 2, ib times
- D1 /5 SHR ew,1 Unsigned divide EA word by 2, once
- D3 /5 SHR ew,CL Unsigned divide EA word by 2, CL times
- C1 /5 ib *SHR ew,ib Unsigned divide EA word by 2, ib times
- 0F 01 /1 *SIDT m Store 6-byte Interrupt Descriptor Table register to M
- 0F 00 /0 *SLDT ew Store Local Descriptor Table register to EA word
- 0F 01 /4 *SMSW ew Store Machine Status Word to EA word
- F9 STC Set carry flag
- FD STD Set direction flag so SI and DI will decrement
- FB STI Set interrupt enable flag, interrupts enabled
- 0F 31/r #STOBITS rb,rb Store AX to ES:DI,bit rb (incr. DI,rb), rb+1 bits
- 0F 39/0 ib #STOBITS rb,ib Store AX to ES:DI,bit rb (incr. DI,rb), ib+1 bits
- AA STOS mb Store AL to byte [DI], advance DI
- AB STOS mw Store AX to word [DI], advance DI
- AA STOSB Store AL to byte ES:[DI], advance DI
- AB STOSW Store AX to word ES:[DI], advance DI
- 0F 00 /1 *STR ew Store Task Register to EA word
- 2C ib SUB AL,ib Subtract immediate byte from AL
- 2D iw SUB AX,iw Subtract immediate word from AX
- 80 /5 ib SUB eb,ib Subtract immediate byte from EA byte
- 28 /r SUB eb,rb Subtract byte register from EA byte
- 83 /5 ib SUB ew,ib Subtract immediate byte from EA word
- 81 /5 iw SUB ew,iw Subtract immediate word from EA word
- 29 /r SUB ew,rw Subtract word register from EA word
- 2A /r SUB rb,eb Subtract EA byte from byte register
- 2B /r SUB rw,ew Subtract EA word from word register
- 0F 22 #SUB4S Sub CL nibbles BCD at DS:SI from ES:DI (CL even,NZ)
- A8 ib TEST AL,ib AND immediate byte into AL for flags only
- A9 iw TEST AX,iw AND immediate word into AX for flags only
- F6 /0 ib TEST eb,ib AND immediate byte into EA byte for flags only
- 84 /r TEST eb,rb AND byte register into EA byte for flags only
- F7 /0 iw TEST ew,iw AND immediate word into EA word for flags only
- 85 /r TEST ew,rw AND word register into EA word for flags only
- 84 /r TEST rb,eb AND EA byte into byte register for flags only
- 85 /r TEST rw,ew AND EA word into word register for flags only
- 0F 10/0 #TESTBIT eb,CL Test bit CL of eb, set Z flag
- 0F 11/0 #TESTBIT ew,CL Test bit CL of ew, set Z flag
- 0F 18/0 ib #TESTBIT eb,ib Test bit ib of eb, set Z flag
- 0F 19/0 ib #TESTBIT ew,ib Test bit ib of ew, set Z flag
- 9B WAIT Wait until BUSY pin is inactive (HIGH)
- 0F 00 /4 *VERR ew Set ZF=1 if segment can be read, selector ew
- 0F 00 /5 *VERW ew Set ZF=1 if segment can be written to, selector ew
- 6-14
-
- 9r XCHG AX,rw Exchange word register with AX
- 86 /r XCHG eb,rb Exchange byte register with EA byte
- 87 /r XCHG ew,rw Exchange word register with EA word
- 86 /r XCHG rb,eb Exchange EA byte with byte register
- 9r XCHG rw,AX Exchange with word register
- 87 /r XCHG rw,ew Exchange EA word with word register
- D7 XLAT mb Set AL to memory byte [BX + unsigned AL]
- D7 XLATB Set AL to memory byte DS:[BX + unsigned AL]
- 34 ib XOR AL,ib Exclusive-OR immediate byte into AL
- 35 iw XOR AX,iw Exclusive-OR immediate word into AX
- 80 /6 ib XOR eb,ib Exclusive-OR immediate byte into EA byte
- 30 /r XOR eb,rb Exclusive-OR byte register into EA byte
- 81 /6 iw XOR ew,iw Exclusive-OR immediate word into EA word
- 31 /r XOR ew,rw Exclusive-OR word register into EA word
- 32 /r XOR rb,eb Exclusive-OR EA byte into byte register
- 33 /r XOR rw,ew Exclusive-OR EA word into word register
-
- * Starred forms will not execute on 8086/8088! See note at top of chart.
- # These instructions work only on NEC chips! See note at top of chart.
-
-